<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\Plugin\WorkMoment\Queue;

use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\AsyncQueue\Annotation\AsyncQueueMessage;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Codec\Json;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use MoChat\App\Corp\Logic\AppTrait;
use MoChat\App\User\Contract\UserContract;
use MoChat\App\Utils\File;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Plugin\WorkMoment\Contract\WorkMomentContract;

/**
 * 企业微信 朋友圈
 * Class MomentApply.
 */
class MomentQueue
{
    use AppTrait;

    /**
     * @Inject
     * @var WorkEmployeeContract
     */
    protected $workEmployeeContract;

    /**
     * @Inject
     * @var WorkMomentContract
     */
    protected $workMomentContract;

    /**
     * @Inject
     * @var UserContract
     */
    protected $userContract;

    /**
     * @Inject
     * @var StdoutLoggerInterface
     */
    private $logger;

    /**
     * @Inject
     * @var Filesystem
     */
    private $filesystem;

    /**
     * @AsyncQueueMessage(pool="default")
     * @param $corpId
     * @throws InvalidConfigException
     * @throws GuzzleException
     * @throws FilesystemException
     */
    public function handle($corpId): void
    {
        // EasyWeChat获取「客户朋友圈」数据
        $params = [
            'start_time' => strtotime(date('Y-m-d', strtotime('-29 day')) . ' 00:00:00'),
            'end_time' => strtotime(date('Y-m-d') . ' 23:59:59'),
        ];
        $result = $this->wxApp($corpId, 'contact')->external_contact_moment->list($params);
        if ($result['errcode'] !== 0) {
            $this->logger->error('客户朋友圈获取企业全部的发表列表失败' . Json::encode($result));
            return;
        }
        $data = [];
        foreach ($result['moment_list'] as $k => $v) {
            if (! empty($this->workMomentContract->getWorkMomentByWxMomentId($v['moment_id']))) {
                continue;
            }

            if (empty($v['creator'])) {
                continue;
            }

            $employee = $this->workEmployeeContract->getWorkEmployeeByCorpIdWxUserId((string) $corpId, $v['creator'], ['id', 'log_user_id']);
            if (empty($employee)) {
                continue;
            }

            $tenant = $this->userContract->getUserById($employee[0]['logUserId'], ['tenant_id']);
            if (empty($tenant)) {
                continue;
            }

            $data[$k] = [
                'wx_moment_id' => $v['moment_id'],
                'creator' => ! empty($v['creator']) ? $v['creator'] : '',
                'create_time' => $v['create_time'],
                'create_type' => $v['create_type'],
                'visible_type' => $v['visible_type'],
                'text' => ! empty($v['text']) ? Json::encode($v['text']) : '{}',
                'image' => ! empty($v['image']) ? $this->getImageMedia($corpId, $v['image']) : '[]',
                'video' => ! empty($v['video']) ? $this->getVideoMedia($corpId, $v['video']) : '{}',
                'link' => ! empty($v['link']) ? Json::encode($v['link']) : '{}',
                'location' => ! empty($v['location']) ? Json::encode($v['location']) : '{}',
                'corp_id' => $corpId,
                'tenant_id' => $tenant['tenantId'] ?? 0,
                'employee_id' => empty($employee) ? 0 : $employee[0]['id'],
                'created_at' => date('Y-m-d H:i:s'),
            ];
        }
        # # 数据操作
        Db::beginTransaction();
        try {
            # # 创建朋友圈记录
            $this->workMomentContract->createWorkMoments(array_merge($data));
            Db::commit();
        } catch (\Throwable $e) {
            Db::rollBack();
            $this->logger->error(sprintf('%s [%s] %s', '朋友圈记录创建失败', date('Y-m-d H:i:s'), $e->getMessage()));
            $this->logger->error($e->getTraceAsString());
            throw new CommonException(ErrorCode::SERVER_ERROR, $e->getMessage()); // '活动创建失败'
        }
    }

    /**
     * 获取临时素材 TODO 需要改为队列形式.
     * @throws InvalidConfigException
     * @throws GuzzleException
     * @throws FilesystemException
     */
    protected function getImageMedia(int $corpId, array $image): string
    {
        foreach ($image as $k => $v) {
            $result = $this->wxApp($corpId, 'contact')->media->get($v['media_id']);
            $image[$k]['image'] = '';
            if (is_object($result)) {
                $filePath = File::generateFullFilename('jpg');
                $this->filesystem->write($filePath, (string) $result);
                $image[$k]['image'] = $filePath;
            }
        }

        return Json::encode($image);
    }

    /**
     * 获取临时素材 TODO 需要改为队列形式.
     * @throws InvalidConfigException
     * @throws GuzzleException
     * @throws FilesystemException
     */
    protected function getVideoMedia(int $corpId, array $video): string
    {
        $result = $this->wxApp($corpId, 'contact')->media->get($video['media_id']);
        $video['video'] = '';
        if (is_object($result)) {
            $filePath = File::generateFullFilename('mp4');
            $this->filesystem->write($filePath, (string) $result);
            $video['video'] = $filePath;
        }
        return Json::encode($video);
    }
}
